package utils

import (
	"bytes"
	"duoke/utils/response"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize"
	"github.com/gin-gonic/gin"
	"io"
	"strings"
	"sync"
)

// RowData 表示Excel中的一行数据
type RowData map[string]interface{}

// ParsedData 表示解析后的单条数据
type ParsedData struct {
	Data      interface{}
	IsValid   bool
	ErrorMsg  string
	RowNumber int
}

// ParserFunc 解析函数类型
type ParserFunc func(row RowData, rowNumber int) (interface{}, bool, string)

// HandlerFunc 处理函数类型
type HandlerFunc func(c *gin.Context, data interface{}) error

// ExcelImporter Excel导入器
type ExcelImporter struct {
	parsers        map[string]ParserFunc
	handlers       map[string]HandlerFunc
	currentContext *gin.Context // 保存当前请求的上下文
}

// NewExcelImporter 创建新的Excel导入器
func NewExcelImporter() *ExcelImporter {
	return &ExcelImporter{
		parsers:  make(map[string]ParserFunc),
		handlers: make(map[string]HandlerFunc),
	}
}

// RegisterParser 注册解析器
func (e *ExcelImporter) RegisterParser(dataType string, parser ParserFunc) {
	e.parsers[dataType] = parser
}

// RegisterHandler 注册处理器
func (e *ExcelImporter) RegisterHandler(dataType string, handler HandlerFunc) {
	e.handlers[dataType] = handler
}

// HandleImport 处理Excel导入请求
func (e *ExcelImporter) HandleImport(c *gin.Context, dataType string) {
	e.currentContext = c
	// 验证数据类型
	parser, ok := e.parsers[dataType]
	if !ok {
		response.Error(c, "不支持的数据类型"+dataType, nil)
		return
	}

	// 获取处理器
	handler, hasHandler := e.handlers[dataType]

	// 从表单中获取上传的文件
	file, err := c.FormFile("file")
	if err != nil {
		response.Error(c, "请选择要上传的Excel文件", nil)
		return
	}

	// 验证文件类型
	if !strings.HasSuffix(strings.ToLower(file.Filename), ".xlsx") &&
		!strings.HasSuffix(strings.ToLower(file.Filename), ".xls") {
		response.Error(c, "请上传.xlsx或.xls格式的Excel文件", nil)
		return
	}

	// 打开文件
	fileContent, err := file.Open()
	if err != nil {
		response.Error(c, "打开文件失败: "+err.Error(), nil)
		return
	}
	defer fileContent.Close()

	// 读取文件内容到内存
	buf, err := io.ReadAll(fileContent)
	if err != nil {
		response.Error(c, "读取文件内容失败: "+err.Error(), nil)
		return
	}

	// 解析Excel文件
	parsedData, err := e.parseExcelWithGoroutines(bytes.NewReader(buf), parser)
	if err != nil {
		response.Error(c, "解析Excel文件失败: "+err.Error(), nil)
		return
	}

	// 如果有处理器，执行数据处理
	if hasHandler {
		err = e.processData(c, parsedData, handler)
		if err != nil {
			response.Error(c, "处理数据失败: "+err.Error(), nil)
			return
		}
	}

	// 计算有效和无效记录数
	validCount := 0
	errorCount := 0
	for _, data := range parsedData {
		if data.IsValid {
			validCount++
		} else {
			errorCount++
		}
	}
	// 返回成功响应
	response.Success(c, "数据导入成功", nil)
}

// parseExcelWithGoroutines 使用协程并行解析Excel文件
func (e *ExcelImporter) parseExcelWithGoroutines(fileReader io.Reader, parser ParserFunc) ([]ParsedData, error) {
	f, err := excelize.OpenReader(fileReader)
	if err != nil {
		return nil, err
	}

	// 获取第一个工作表
	sheetName := f.GetSheetName(1)

	// 获取所有行
	rows := f.GetRows(sheetName)
	// 跳过空文件
	if len(rows) <= 1 {
		return []ParsedData{}, nil
	}

	// 获取表头
	headers := rows[0]

	// 创建结果通道和错误通道
	resultCh := make(chan ParsedData)
	errorCh := make(chan error)
	doneCh := make(chan struct{})

	// 启动一个goroutine来监听错误
	go func() {
		if err := <-errorCh; err != nil {
			close(doneCh)
			close(resultCh)
			close(errorCh)
		}
	}()

	// 定义worker数量（根据CPU核心数调整）
	workers := 4
	var wg sync.WaitGroup

	// 创建任务通道
	taskCh := make(chan int)

	// 启动worker协程
	for i := 0; i < workers; i++ {
		wg.Add(1)
		go func(workerID int) {
			defer wg.Done()
			for rowIndex := range taskCh {
				select {
				case <-doneCh:
					return
				default:
					// 将行数据转换为map
					rowMap := make(RowData)
					for colIndex, header := range headers {
						if colIndex < len(rows[rowIndex]) {
							rowMap[header] = rows[rowIndex][colIndex]
						}
					}

					// 解析数据
					data, isValid, errorMsg := parser(rowMap, rowIndex+1)
					resultCh <- ParsedData{
						Data:      data,
						IsValid:   isValid,
						ErrorMsg:  errorMsg,
						RowNumber: rowIndex + 1,
					}
				}
			}
		}(i)
	}

	// 发送任务到任务通道（跳过标题行）
	go func() {
		for i := 1; i < len(rows); i++ {
			taskCh <- i
		}
		close(taskCh)
	}()

	// 等待所有worker完成
	go func() {
		wg.Wait()
		close(resultCh)
	}()

	// 收集结果
	var parsedData []ParsedData
	for data := range resultCh {
		parsedData = append(parsedData, data)
	}

	// 检查是否有错误
	select {
	case err := <-errorCh:
		return nil, err
	default:
		return parsedData, nil
	}
}

// processData 处理解析后的数据
func (e *ExcelImporter) processData(c *gin.Context, data []ParsedData, handler HandlerFunc) error {
	// 这里可以实现批量处理或并行处理
	// 为简化示例，这里使用串行处理
	for _, item := range data {
		if item.IsValid {
			if err := handler(c, item.Data); err != nil {
				return fmt.Errorf("处理第 %d 行数据失败: %v", item.RowNumber, err)
			}
		}
	}
	return nil
}

// min 返回两个整数中的较小值
func initmin(a, b int) int {
	if a < b {
		return a
	}
	return b
}
